{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from __future__ import print_function\n",
    "\n",
    "import math\n",
    "\n",
    "from IPython import display\n",
    "from matplotlib import cm\n",
    "from matplotlib import gridspec\n",
    "from matplotlib import pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from sklearn import metrics\n",
    "import tensorflow as tf\n",
    "from tensorflow.python.data import Dataset\n",
    "\n",
    "tf.logging.set_verbosity(tf.logging.ERROR)\n",
    "pd.options.display.max_rows = 10\n",
    "pd.options.display.float_format = '{:.1f}'.format\n",
    "\n",
    "california_housing_dataframe = pd.read_csv(\"https://dl.google.com/mlcc/mledu-datasets/california_housing_train.csv\", sep=\",\")\n",
    "\n",
    "california_housing_dataframe = california_housing_dataframe.reindex(\n",
    "    np.random.permutation(california_housing_dataframe.index))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def preprocess_features(california_housing_dataframe):\n",
    "  \"\"\"Prepares input features from California housing data set.\n",
    "\n",
    "  Args:\n",
    "    california_housing_dataframe: A Pandas DataFrame expected to contain data\n",
    "      from the California housing data set.\n",
    "  Returns:\n",
    "    A DataFrame that contains the features to be used for the model, including\n",
    "    synthetic features.\n",
    "  \"\"\"\n",
    "  selected_features = california_housing_dataframe[\n",
    "    [\"latitude\",\n",
    "     \"longitude\",\n",
    "     \"housing_median_age\",\n",
    "     \"total_rooms\",\n",
    "     \"total_bedrooms\",\n",
    "     \"population\",\n",
    "     \"households\",\n",
    "     \"median_income\"]]\n",
    "  processed_features = selected_features.copy()\n",
    "  # Create a synthetic feature.\n",
    "  processed_features[\"rooms_per_person\"] = (\n",
    "    california_housing_dataframe[\"total_rooms\"] /\n",
    "    california_housing_dataframe[\"population\"])\n",
    "  return processed_features\n",
    "\n",
    "def preprocess_targets(california_housing_dataframe):\n",
    "  \"\"\"Prepares target features (i.e., labels) from California housing data set.\n",
    "\n",
    "  Args:\n",
    "    california_housing_dataframe: A Pandas DataFrame expected to contain data\n",
    "      from the California housing data set.\n",
    "  Returns:\n",
    "    A DataFrame that contains the target feature.\n",
    "  \"\"\"\n",
    "  output_targets = pd.DataFrame()\n",
    "  # Scale the target to be in units of thousands of dollars.\n",
    "  output_targets[\"median_house_value\"] = (\n",
    "    california_housing_dataframe[\"median_house_value\"] / 1000.0)\n",
    "  return output_targets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training examples summary:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>latitude</th>\n",
       "      <th>longitude</th>\n",
       "      <th>housing_median_age</th>\n",
       "      <th>total_rooms</th>\n",
       "      <th>total_bedrooms</th>\n",
       "      <th>population</th>\n",
       "      <th>households</th>\n",
       "      <th>median_income</th>\n",
       "      <th>rooms_per_person</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "      <td>12000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>35.6</td>\n",
       "      <td>-119.6</td>\n",
       "      <td>28.6</td>\n",
       "      <td>2647.7</td>\n",
       "      <td>540.7</td>\n",
       "      <td>1436.5</td>\n",
       "      <td>501.9</td>\n",
       "      <td>3.9</td>\n",
       "      <td>2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>2.1</td>\n",
       "      <td>2.0</td>\n",
       "      <td>12.6</td>\n",
       "      <td>2210.1</td>\n",
       "      <td>426.4</td>\n",
       "      <td>1174.1</td>\n",
       "      <td>387.9</td>\n",
       "      <td>1.9</td>\n",
       "      <td>1.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>32.5</td>\n",
       "      <td>-124.3</td>\n",
       "      <td>1.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>33.9</td>\n",
       "      <td>-121.8</td>\n",
       "      <td>18.0</td>\n",
       "      <td>1461.8</td>\n",
       "      <td>296.0</td>\n",
       "      <td>787.0</td>\n",
       "      <td>281.0</td>\n",
       "      <td>2.6</td>\n",
       "      <td>1.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>34.3</td>\n",
       "      <td>-118.5</td>\n",
       "      <td>29.0</td>\n",
       "      <td>2130.0</td>\n",
       "      <td>436.0</td>\n",
       "      <td>1168.0</td>\n",
       "      <td>410.0</td>\n",
       "      <td>3.5</td>\n",
       "      <td>1.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>37.7</td>\n",
       "      <td>-118.0</td>\n",
       "      <td>37.0</td>\n",
       "      <td>3153.0</td>\n",
       "      <td>651.0</td>\n",
       "      <td>1726.0</td>\n",
       "      <td>607.0</td>\n",
       "      <td>4.7</td>\n",
       "      <td>2.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>42.0</td>\n",
       "      <td>-114.5</td>\n",
       "      <td>52.0</td>\n",
       "      <td>37937.0</td>\n",
       "      <td>6445.0</td>\n",
       "      <td>35682.0</td>\n",
       "      <td>6082.0</td>\n",
       "      <td>15.0</td>\n",
       "      <td>55.2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       latitude  longitude  housing_median_age  total_rooms  total_bedrooms  \\\n",
       "count   12000.0    12000.0             12000.0      12000.0         12000.0   \n",
       "mean       35.6     -119.6                28.6       2647.7           540.7   \n",
       "std         2.1        2.0                12.6       2210.1           426.4   \n",
       "min        32.5     -124.3                 1.0          2.0             1.0   \n",
       "25%        33.9     -121.8                18.0       1461.8           296.0   \n",
       "50%        34.3     -118.5                29.0       2130.0           436.0   \n",
       "75%        37.7     -118.0                37.0       3153.0           651.0   \n",
       "max        42.0     -114.5                52.0      37937.0          6445.0   \n",
       "\n",
       "       population  households  median_income  rooms_per_person  \n",
       "count     12000.0     12000.0        12000.0           12000.0  \n",
       "mean       1436.5       501.9            3.9               2.0  \n",
       "std        1174.1       387.9            1.9               1.2  \n",
       "min           3.0         1.0            0.5               0.0  \n",
       "25%         787.0       281.0            2.6               1.5  \n",
       "50%        1168.0       410.0            3.5               1.9  \n",
       "75%        1726.0       607.0            4.7               2.3  \n",
       "max       35682.0      6082.0           15.0              55.2  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Validation examples summary:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>latitude</th>\n",
       "      <th>longitude</th>\n",
       "      <th>housing_median_age</th>\n",
       "      <th>total_rooms</th>\n",
       "      <th>total_bedrooms</th>\n",
       "      <th>population</th>\n",
       "      <th>households</th>\n",
       "      <th>median_income</th>\n",
       "      <th>rooms_per_person</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "      <td>5000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>35.6</td>\n",
       "      <td>-119.5</td>\n",
       "      <td>28.5</td>\n",
       "      <td>2634.1</td>\n",
       "      <td>536.2</td>\n",
       "      <td>1413.0</td>\n",
       "      <td>499.7</td>\n",
       "      <td>3.9</td>\n",
       "      <td>2.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>2.1</td>\n",
       "      <td>2.0</td>\n",
       "      <td>12.6</td>\n",
       "      <td>2105.9</td>\n",
       "      <td>409.5</td>\n",
       "      <td>1082.1</td>\n",
       "      <td>376.4</td>\n",
       "      <td>1.9</td>\n",
       "      <td>1.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>32.6</td>\n",
       "      <td>-124.3</td>\n",
       "      <td>1.0</td>\n",
       "      <td>11.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>8.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>0.5</td>\n",
       "      <td>0.2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>33.9</td>\n",
       "      <td>-121.8</td>\n",
       "      <td>18.0</td>\n",
       "      <td>1463.0</td>\n",
       "      <td>297.0</td>\n",
       "      <td>795.0</td>\n",
       "      <td>282.0</td>\n",
       "      <td>2.6</td>\n",
       "      <td>1.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>34.2</td>\n",
       "      <td>-118.5</td>\n",
       "      <td>28.0</td>\n",
       "      <td>2120.5</td>\n",
       "      <td>430.0</td>\n",
       "      <td>1163.0</td>\n",
       "      <td>406.0</td>\n",
       "      <td>3.6</td>\n",
       "      <td>1.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>37.7</td>\n",
       "      <td>-118.0</td>\n",
       "      <td>37.0</td>\n",
       "      <td>3142.2</td>\n",
       "      <td>645.0</td>\n",
       "      <td>1705.5</td>\n",
       "      <td>598.0</td>\n",
       "      <td>4.8</td>\n",
       "      <td>2.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>41.9</td>\n",
       "      <td>-114.3</td>\n",
       "      <td>52.0</td>\n",
       "      <td>27700.0</td>\n",
       "      <td>4798.0</td>\n",
       "      <td>15037.0</td>\n",
       "      <td>4490.0</td>\n",
       "      <td>15.0</td>\n",
       "      <td>52.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       latitude  longitude  housing_median_age  total_rooms  total_bedrooms  \\\n",
       "count    5000.0     5000.0              5000.0       5000.0          5000.0   \n",
       "mean       35.6     -119.5                28.5       2634.1           536.2   \n",
       "std         2.1        2.0                12.6       2105.9           409.5   \n",
       "min        32.6     -124.3                 1.0         11.0             4.0   \n",
       "25%        33.9     -121.8                18.0       1463.0           297.0   \n",
       "50%        34.2     -118.5                28.0       2120.5           430.0   \n",
       "75%        37.7     -118.0                37.0       3142.2           645.0   \n",
       "max        41.9     -114.3                52.0      27700.0          4798.0   \n",
       "\n",
       "       population  households  median_income  rooms_per_person  \n",
       "count      5000.0      5000.0         5000.0            5000.0  \n",
       "mean       1413.0       499.7            3.9               2.0  \n",
       "std        1082.1       376.4            1.9               1.2  \n",
       "min           8.0         2.0            0.5               0.2  \n",
       "25%         795.0       282.0            2.6               1.5  \n",
       "50%        1163.0       406.0            3.6               1.9  \n",
       "75%        1705.5       598.0            4.8               2.3  \n",
       "max       15037.0      4490.0           15.0              52.0  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training targets summary:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>median_house_value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>12000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>206.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>116.1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>17.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>118.6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>179.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>263.8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>500.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       median_house_value\n",
       "count             12000.0\n",
       "mean                206.5\n",
       "std                 116.1\n",
       "min                  17.5\n",
       "25%                 118.6\n",
       "50%                 179.5\n",
       "75%                 263.8\n",
       "max                 500.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Validation targets summary:\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>median_house_value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>5000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>209.3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>115.8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>15.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>121.9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>181.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>267.4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>500.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       median_house_value\n",
       "count              5000.0\n",
       "mean                209.3\n",
       "std                 115.8\n",
       "min                  15.0\n",
       "25%                 121.9\n",
       "50%                 181.4\n",
       "75%                 267.4\n",
       "max                 500.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Choose the first 12000 (out of 17000) examples for training.\n",
    "training_examples = preprocess_features(california_housing_dataframe.head(12000))\n",
    "training_targets = preprocess_targets(california_housing_dataframe.head(12000))\n",
    "\n",
    "# Choose the last 5000 (out of 17000) examples for validation.\n",
    "validation_examples = preprocess_features(california_housing_dataframe.tail(5000))\n",
    "validation_targets = preprocess_targets(california_housing_dataframe.tail(5000))\n",
    "\n",
    "# Double-check that we've done the right thing.\n",
    "print(\"Training examples summary:\")\n",
    "display.display(training_examples.describe())\n",
    "print(\"Validation examples summary:\")\n",
    "display.display(validation_examples.describe())\n",
    "\n",
    "print(\"Training targets summary:\")\n",
    "display.display(training_targets.describe())\n",
    "print(\"Validation targets summary:\")\n",
    "display.display(validation_targets.describe())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def construct_feature_columns(input_features):\n",
    "  \"\"\"Construct the TensorFlow Feature Columns.\n",
    "\n",
    "  Args:\n",
    "    input_features: The names of the numerical input features to use.\n",
    "  Returns:\n",
    "    A set of feature columns\n",
    "  \"\"\"\n",
    "  return set([tf.feature_column.numeric_column(my_feature)\n",
    "              for my_feature in input_features])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):\n",
    "    \"\"\"Trains a linear regression model of one feature.\n",
    "  \n",
    "    Args:\n",
    "      features: pandas DataFrame of features\n",
    "      targets: pandas DataFrame of targets\n",
    "      batch_size: Size of batches to be passed to the model\n",
    "      shuffle: True or False. Whether to shuffle the data.\n",
    "      num_epochs: Number of epochs for which data should be repeated. None = repeat indefinitely\n",
    "    Returns:\n",
    "      Tuple of (features, labels) for next data batch\n",
    "    \"\"\"\n",
    "    \n",
    "    # Convert pandas data into a dict of np arrays.\n",
    "    features = {key:np.array(value) for key,value in dict(features).items()}                                           \n",
    " \n",
    "    # Construct a dataset, and configure batching/repeating\n",
    "    ds = Dataset.from_tensor_slices((features,targets)) # warning: 2GB limit\n",
    "    ds = ds.batch(batch_size).repeat(num_epochs)\n",
    "    \n",
    "    # Shuffle the data, if specified\n",
    "    if shuffle:\n",
    "      ds = ds.shuffle(10000)\n",
    "    \n",
    "    # Return the next batch of data\n",
    "    features, labels = ds.make_one_shot_iterator().get_next()\n",
    "    return features, labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_model(\n",
    "    learning_rate,\n",
    "    steps,\n",
    "    batch_size,\n",
    "    feature_columns,\n",
    "    training_examples,\n",
    "    training_targets,\n",
    "    validation_examples,\n",
    "    validation_targets):\n",
    "  \"\"\"Trains a linear regression model.\n",
    "  \n",
    "  In addition to training, this function also prints training progress information,\n",
    "  as well as a plot of the training and validation loss over time.\n",
    "  \n",
    "  Args:\n",
    "    learning_rate: A `float`, the learning rate.\n",
    "    steps: A non-zero `int`, the total number of training steps. A training step\n",
    "      consists of a forward and backward pass using a single batch.\n",
    "    feature_columns: A `set` specifying the input feature columns to use.\n",
    "    training_examples: A `DataFrame` containing one or more columns from\n",
    "      `california_housing_dataframe` to use as input features for training.\n",
    "    training_targets: A `DataFrame` containing exactly one column from\n",
    "      `california_housing_dataframe` to use as target for training.\n",
    "    validation_examples: A `DataFrame` containing one or more columns from\n",
    "      `california_housing_dataframe` to use as input features for validation.\n",
    "    validation_targets: A `DataFrame` containing exactly one column from\n",
    "      `california_housing_dataframe` to use as target for validation.\n",
    "      \n",
    "  Returns:\n",
    "    A `LinearRegressor` object trained on the training data.\n",
    "  \"\"\"\n",
    "\n",
    "  periods = 10\n",
    "  steps_per_period = steps / periods\n",
    "\n",
    "  # Create a linear regressor object.\n",
    "  my_optimizer = tf.train.FtrlOptimizer(learning_rate=learning_rate)\n",
    "  my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)\n",
    "  linear_regressor = tf.estimator.LinearRegressor(\n",
    "      feature_columns=feature_columns,\n",
    "      optimizer=my_optimizer\n",
    "  )\n",
    "  \n",
    "  training_input_fn = lambda: my_input_fn(training_examples, \n",
    "                                          training_targets[\"median_house_value\"], \n",
    "                                          batch_size=batch_size)\n",
    "  predict_training_input_fn = lambda: my_input_fn(training_examples, \n",
    "                                                  training_targets[\"median_house_value\"], \n",
    "                                                  num_epochs=1, \n",
    "                                                  shuffle=False)\n",
    "  predict_validation_input_fn = lambda: my_input_fn(validation_examples, \n",
    "                                                    validation_targets[\"median_house_value\"], \n",
    "                                                    num_epochs=1, \n",
    "                                                    shuffle=False)\n",
    "\n",
    "  # Train the model, but do so inside a loop so that we can periodically assess\n",
    "  # loss metrics.\n",
    "  print(\"Training model...\")\n",
    "  print(\"RMSE (on training data):\")\n",
    "  training_rmse = []\n",
    "  validation_rmse = []\n",
    "  for period in range (0, periods):\n",
    "    # Train the model, starting from the prior state.\n",
    "    linear_regressor.train(\n",
    "        input_fn=training_input_fn,\n",
    "        steps=steps_per_period\n",
    "    )\n",
    "    # Take a break and compute predictions.\n",
    "    training_predictions = linear_regressor.predict(input_fn=predict_training_input_fn)\n",
    "    training_predictions = np.array([item['predictions'][0] for item in training_predictions])\n",
    "    validation_predictions = linear_regressor.predict(input_fn=predict_validation_input_fn)\n",
    "    validation_predictions = np.array([item['predictions'][0] for item in validation_predictions])\n",
    "    \n",
    "    # Compute training and validation loss.\n",
    "    training_root_mean_squared_error = math.sqrt(\n",
    "        metrics.mean_squared_error(training_predictions, training_targets))\n",
    "    validation_root_mean_squared_error = math.sqrt(\n",
    "        metrics.mean_squared_error(validation_predictions, validation_targets))\n",
    "    # Occasionally print the current loss.\n",
    "    print(\"  period %02d : %0.2f\" % (period, training_root_mean_squared_error))\n",
    "    # Add the loss metrics from this period to our list.\n",
    "    training_rmse.append(training_root_mean_squared_error)\n",
    "    validation_rmse.append(validation_root_mean_squared_error)\n",
    "  print(\"Model training finished.\")\n",
    "\n",
    "  \n",
    "  # Output a graph of loss metrics over periods.\n",
    "  plt.ylabel(\"RMSE\")\n",
    "  plt.xlabel(\"Periods\")\n",
    "  plt.title(\"Root Mean Squared Error vs. Periods\")\n",
    "  plt.tight_layout()\n",
    "  plt.plot(training_rmse, label=\"training\")\n",
    "  plt.plot(validation_rmse, label=\"validation\")\n",
    "  plt.legend()\n",
    "\n",
    "  return linear_regressor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training model...\n",
      "RMSE (on training data):\n",
      "  period 00 : 183.61\n",
      "  period 01 : 122.07\n",
      "  period 02 : 124.77\n",
      "  period 03 : 117.50\n",
      "  period 04 : 148.58\n",
      "  period 05 : 132.55\n",
      "  period 06 : 143.10\n",
      "  period 07 : 124.81\n",
      "  period 08 : 116.51\n",
      "  period 09 : 115.18\n",
      "Model training finished.\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "_ = train_model(\n",
    "    learning_rate=1.0,\n",
    "    steps=500,\n",
    "    batch_size=100,\n",
    "    feature_columns=construct_feature_columns(training_examples),\n",
    "    training_examples=training_examples,\n",
    "    training_targets=training_targets,\n",
    "    validation_examples=validation_examples,\n",
    "    validation_targets=validation_targets)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_quantile_based_boundaries(feature_values, num_buckets):\n",
    "  boundaries = np.arange(1.0, num_buckets) / num_buckets\n",
    "  quantiles = feature_values.quantile(boundaries)\n",
    "  return [quantiles[q] for q in quantiles.keys()]\n",
    "\n",
    "# Divide households into 7 buckets.\n",
    "households = tf.feature_column.numeric_column(\"households\")\n",
    "bucketized_households = tf.feature_column.bucketized_column(\n",
    "  households, boundaries=get_quantile_based_boundaries(\n",
    "    california_housing_dataframe[\"households\"], 7))\n",
    "\n",
    "# Divide longitude into 10 buckets.\n",
    "longitude = tf.feature_column.numeric_column(\"longitude\")\n",
    "bucketized_longitude = tf.feature_column.bucketized_column(\n",
    "  longitude, boundaries=get_quantile_based_boundaries(\n",
    "    california_housing_dataframe[\"longitude\"], 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Assignment 1:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "def construct_feature_columns():\n",
    "  \"\"\"Construct the TensorFlow Feature Columns.\n",
    "\n",
    "  Returns:\n",
    "    A set of feature columns\n",
    "  \"\"\" \n",
    "  households = tf.feature_column.numeric_column(\"households\")\n",
    "  longitude = tf.feature_column.numeric_column(\"longitude\")\n",
    "  latitude = tf.feature_column.numeric_column(\"latitude\")\n",
    "  housing_median_age = tf.feature_column.numeric_column(\"housing_median_age\")\n",
    "  median_income = tf.feature_column.numeric_column(\"median_income\")\n",
    "  rooms_per_person = tf.feature_column.numeric_column(\"rooms_per_person\")\n",
    "  \n",
    "  # Divide households into 7 buckets.\n",
    "  bucketized_households = tf.feature_column.bucketized_column(\n",
    "    households, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"households\"], 7))\n",
    "\n",
    "  # Divide longitude into 10 buckets.\n",
    "  bucketized_longitude = tf.feature_column.bucketized_column(\n",
    "    longitude, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"longitude\"], 10))\n",
    "\n",
    "  #\n",
    "  # YOUR CODE HERE: bucketize the following columns, following the example above:\n",
    "  #\n",
    "  bucketized_latitude = tf.feature_column.bucketized_column(\n",
    "    latitude, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"latitude\"], 10))\n",
    "  bucketized_housing_median_age = tf.feature_column.bucketized_column(\n",
    "    housing_median_age, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"housing_median_age\"], 7))\n",
    "  bucketized_median_income = tf.feature_column.bucketized_column(\n",
    "    median_income, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"median_income\"], 7))\n",
    "  bucketized_rooms_per_person = tf.feature_column.bucketized_column(\n",
    "    rooms_per_person, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"rooms_per_person\"], 7))\n",
    "  \n",
    "  feature_columns = set([\n",
    "    bucketized_longitude,\n",
    "    bucketized_latitude,\n",
    "    bucketized_housing_median_age,\n",
    "    bucketized_households,\n",
    "    bucketized_median_income,\n",
    "    bucketized_rooms_per_person])\n",
    "  \n",
    "  return feature_columns\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training model...\n",
      "RMSE (on training data):\n",
      "  period 00 : 168.93\n",
      "  period 01 : 142.78\n",
      "  period 02 : 126.44\n",
      "  period 03 : 115.36\n",
      "  period 04 : 107.54\n",
      "  period 05 : 101.72\n",
      "  period 06 : 97.20\n",
      "  period 07 : 93.67\n",
      "  period 08 : 90.71\n",
      "  period 09 : 88.22\n",
      "Model training finished.\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "_ = train_model(\n",
    "    learning_rate=1.0,\n",
    "    steps=500,\n",
    "    batch_size=100,\n",
    "    feature_columns=construct_feature_columns(),\n",
    "    training_examples=training_examples,\n",
    "    training_targets=training_targets,\n",
    "    validation_examples=validation_examples,\n",
    "    validation_targets=validation_targets)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Assignment2:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def construct_feature_columns():\n",
    "  \"\"\"Construct the TensorFlow Feature Columns.\n",
    "\n",
    "  Returns:\n",
    "    A set of feature columns\n",
    "  \"\"\" \n",
    "  households = tf.feature_column.numeric_column(\"households\")\n",
    "  longitude = tf.feature_column.numeric_column(\"longitude\")\n",
    "  latitude = tf.feature_column.numeric_column(\"latitude\")\n",
    "  housing_median_age = tf.feature_column.numeric_column(\"housing_median_age\")\n",
    "  median_income = tf.feature_column.numeric_column(\"median_income\")\n",
    "  rooms_per_person = tf.feature_column.numeric_column(\"rooms_per_person\")\n",
    "  \n",
    "  # Divide households into 7 buckets.\n",
    "  bucketized_households = tf.feature_column.bucketized_column(\n",
    "    households, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"households\"], 7))\n",
    "\n",
    "  # Divide longitude into 10 buckets.\n",
    "  bucketized_longitude = tf.feature_column.bucketized_column(\n",
    "    longitude, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"longitude\"], 10))\n",
    "  \n",
    "  # Divide latitude into 10 buckets.\n",
    "  bucketized_latitude = tf.feature_column.bucketized_column(\n",
    "    latitude, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"latitude\"], 10))\n",
    "\n",
    "  # Divide housing_median_age into 7 buckets.\n",
    "  bucketized_housing_median_age = tf.feature_column.bucketized_column(\n",
    "    housing_median_age, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"housing_median_age\"], 7))\n",
    "  \n",
    "  # Divide median_income into 7 buckets.\n",
    "  bucketized_median_income = tf.feature_column.bucketized_column(\n",
    "    median_income, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"median_income\"], 7))\n",
    "  \n",
    "  # Divide rooms_per_person into 7 buckets.\n",
    "  bucketized_rooms_per_person = tf.feature_column.bucketized_column(\n",
    "    rooms_per_person, boundaries=get_quantile_based_boundaries(\n",
    "      training_examples[\"rooms_per_person\"], 7))\n",
    "  \n",
    "  # YOUR CODE HERE: Make a feature column for the long_x_lat feature cross\n",
    "  long_x_lat = tf.feature_column.crossed_column(set([bucketized_longitude,bucketized_latitude]),hash_bucket_size=1000)\n",
    "  \n",
    "  feature_columns = set([\n",
    "    bucketized_longitude,\n",
    "    bucketized_latitude,\n",
    "    bucketized_housing_median_age,\n",
    "    bucketized_households,\n",
    "    bucketized_median_income,\n",
    "    bucketized_rooms_per_person,\n",
    "    long_x_lat])\n",
    "  \n",
    "  return feature_columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training model...\n",
      "RMSE (on training data):\n",
      "  period 00 : 162.55\n",
      "  period 01 : 134.34\n",
      "  period 02 : 117.28\n",
      "  period 03 : 105.92\n",
      "  period 04 : 98.01\n",
      "  period 05 : 92.24\n",
      "  period 06 : 87.75\n",
      "  period 07 : 84.13\n",
      "  period 08 : 81.33\n",
      "  period 09 : 78.99\n",
      "Model training finished.\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "_ = train_model(\n",
    "    learning_rate=1.0,\n",
    "    steps=500,\n",
    "    batch_size=100,\n",
    "    feature_columns=construct_feature_columns(),\n",
    "    training_examples=training_examples,\n",
    "    training_targets=training_targets,\n",
    "    validation_examples=validation_examples,\n",
    "    validation_targets=validation_targets)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.15"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
